using System;
using System.Drawing;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Configuration;
using System.IO;
using IO = System.IO;
using System.Windows.Forms;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Text.RegularExpressions;
using System.Threading;
using DMO = SQLDMO;
using Dimok;
using Dimok.Data.Database;
using Dimok.Exceptions;

namespace SQLDIMOK {
	public class FormMain : System.Windows.Forms.Form{
		#region Members
		object m = System.Reflection.Missing.Value;
		private System.Windows.Forms.Button btnConnect;
		private System.Windows.Forms.DataGrid dgDBObjects;
		private System.Windows.Forms.TextBox txtTemplate;
		private System.Windows.Forms.Label label1;
		private System.Windows.Forms.Label label2;
		private System.Windows.Forms.Label label3;
		private System.Windows.Forms.Label label4;
		private System.Windows.Forms.ContextMenu cmObject;
		private System.Windows.Forms.MenuItem miCompare;
		private System.Windows.Forms.MenuItem miCopy;
		private System.Windows.Forms.ComboBox cmbDBFrom;
		private System.Windows.Forms.ComboBox cmbTo;
		private System.Windows.Forms.StatusBar stBar;
		private System.Windows.Forms.MenuItem menuItem2;
		private System.Windows.Forms.Button btnRemEquals;
		private System.Windows.Forms.Button btnRefresh;
		private System.Windows.Forms.MenuItem cmnuObject;
		private System.Windows.Forms.MenuItem cmnuDepends;
		private System.Windows.Forms.MenuItem cmnuDrop;
		private System.Windows.Forms.MenuItem cmnuRename;
		private System.Windows.Forms.Button btmSave;
		private System.Windows.Forms.Button btnOpen;
		private System.Windows.Forms.SaveFileDialog saveFileDlg;
		private System.Windows.Forms.StatusBarPanel spnlObjectName;
		private System.Windows.Forms.StatusBarPanel spnlLeft;
		private System.Windows.Forms.CheckBox chkPercsent;
		private System.Windows.Forms.DataGridTableStyle dataGridTableStyle1;
		private System.Windows.Forms.MenuItem miEdit;
		private System.Windows.Forms.TextBox txtServerFrom;
		private System.Windows.Forms.TextBox txtServerTo;
		private System.Windows.Forms.Label label5;
		private System.Windows.Forms.TextBox txtPath;
		private System.Windows.Forms.FolderBrowserDialog dlgPath;
		private System.Windows.Forms.Button button1;
		#endregion
		private System.Windows.Forms.MenuItem menuItem3;
		private System.Windows.Forms.MenuItem miCreate;
		private System.Windows.Forms.MenuItem menuItem4;
		private System.Windows.Forms.Button btnAbort;
		private System.Windows.Forms.MenuItem miShow;
		private System.Windows.Forms.MenuItem miMakeSP;
		private System.Windows.Forms.MenuItem miShowSP;
		private System.Windows.Forms.MenuItem miShowVersions;
		private System.Windows.Forms.MenuItem miTrace;
		private System.Windows.Forms.TextBox txtSchema;
		private System.Windows.Forms.Label label6;
		private System.Windows.Forms.TextBox txtType;
		private System.Windows.Forms.Label label7;
		private System.Windows.Forms.OpenFileDialog dlgSqlFiles;
		private MenuItem miSave;

		#region Form Staff
		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;

		public FormMain(string serverFrom,string serverTo,string dbFrom,string dbTo,string dbTemplate,DBObjectsDS dsDBObjects):this(){
			FillPersistTable(serverFrom,serverTo,dbFrom,dbTo,dbTemplate);
			DBTemplate = dbTemplate;
			chkPercsent.Checked = dbTemplate.IndexOf("%") == 0;
			if( dsDBObjects != null ) this.dsDBObjects.Merge(dsDBObjects.Objects);
			dontRestore = true;
		}
		public FormMain() {
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();

		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing ) {
			if( disposing ) {
				if (components != null) {
					components.Dispose();
				}
			}
			this.Invoke(new Action(() => base.Dispose(disposing)));
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent() {
			System.Configuration.AppSettingsReader configurationAppSettings = new System.Configuration.AppSettingsReader();
			this.btnConnect = new System.Windows.Forms.Button();
			this.dgDBObjects = new System.Windows.Forms.DataGrid();
			this.cmObject = new System.Windows.Forms.ContextMenu();
			this.miCompare = new System.Windows.Forms.MenuItem();
			this.miShow = new System.Windows.Forms.MenuItem();
			this.miEdit = new System.Windows.Forms.MenuItem();
			this.miSave = new System.Windows.Forms.MenuItem();
			this.miCopy = new System.Windows.Forms.MenuItem();
			this.menuItem2 = new System.Windows.Forms.MenuItem();
			this.cmnuObject = new System.Windows.Forms.MenuItem();
			this.cmnuDepends = new System.Windows.Forms.MenuItem();
			this.miShowVersions = new System.Windows.Forms.MenuItem();
			this.miCreate = new System.Windows.Forms.MenuItem();
			this.cmnuRename = new System.Windows.Forms.MenuItem();
			this.miMakeSP = new System.Windows.Forms.MenuItem();
			this.miShowSP = new System.Windows.Forms.MenuItem();
			this.miTrace = new System.Windows.Forms.MenuItem();
			this.cmnuDrop = new System.Windows.Forms.MenuItem();
			this.menuItem3 = new System.Windows.Forms.MenuItem();
			this.menuItem4 = new System.Windows.Forms.MenuItem();
			this.dataGridTableStyle1 = new System.Windows.Forms.DataGridTableStyle();
			this.txtTemplate = new System.Windows.Forms.TextBox();
			this.txtServerFrom = new System.Windows.Forms.TextBox();
			this.label1 = new System.Windows.Forms.Label();
			this.label2 = new System.Windows.Forms.Label();
			this.label3 = new System.Windows.Forms.Label();
			this.label4 = new System.Windows.Forms.Label();
			this.cmbDBFrom = new System.Windows.Forms.ComboBox();
			this.cmbTo = new System.Windows.Forms.ComboBox();
			this.stBar = new System.Windows.Forms.StatusBar();
			this.spnlObjectName = new System.Windows.Forms.StatusBarPanel();
			this.spnlLeft = new System.Windows.Forms.StatusBarPanel();
			this.btnRemEquals = new System.Windows.Forms.Button();
			this.btnRefresh = new System.Windows.Forms.Button();
			this.btmSave = new System.Windows.Forms.Button();
			this.btnOpen = new System.Windows.Forms.Button();
			this.saveFileDlg = new System.Windows.Forms.SaveFileDialog();
			this.chkPercsent = new System.Windows.Forms.CheckBox();
			this.txtServerTo = new System.Windows.Forms.TextBox();
			this.label5 = new System.Windows.Forms.Label();
			this.txtPath = new System.Windows.Forms.TextBox();
			this.dlgPath = new System.Windows.Forms.FolderBrowserDialog();
			this.button1 = new System.Windows.Forms.Button();
			this.btnAbort = new System.Windows.Forms.Button();
			this.txtSchema = new System.Windows.Forms.TextBox();
			this.label6 = new System.Windows.Forms.Label();
			this.txtType = new System.Windows.Forms.TextBox();
			this.label7 = new System.Windows.Forms.Label();
			this.dlgSqlFiles = new System.Windows.Forms.OpenFileDialog();
			((System.ComponentModel.ISupportInitialize)(this.dgDBObjects)).BeginInit();
			((System.ComponentModel.ISupportInitialize)(this.spnlObjectName)).BeginInit();
			((System.ComponentModel.ISupportInitialize)(this.spnlLeft)).BeginInit();
			this.SuspendLayout();
			// 
			// btnConnect
			// 
			this.btnConnect.Location = new System.Drawing.Point(4, 0);
			this.btnConnect.Name = "btnConnect";
			this.btnConnect.Size = new System.Drawing.Size(56, 23);
			this.btnConnect.TabIndex = 6;
			this.btnConnect.TabStop = false;
			this.btnConnect.Text = "Fetch";
			this.btnConnect.Click += new System.EventHandler(this.btnConnect_Click);
			// 
			// dgDBObjects
			// 
			this.dgDBObjects.AllowSorting = false;
			this.dgDBObjects.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
									| System.Windows.Forms.AnchorStyles.Left)
									| System.Windows.Forms.AnchorStyles.Right)));
			this.dgDBObjects.CaptionVisible = false;
			this.dgDBObjects.ContextMenu = this.cmObject;
			this.dgDBObjects.DataMember = "";
			this.dgDBObjects.HeaderForeColor = System.Drawing.SystemColors.ControlText;
			this.dgDBObjects.Location = new System.Drawing.Point(0, 48);
			this.dgDBObjects.Name = "dgDBObjects";
			this.dgDBObjects.ReadOnly = true;
			this.dgDBObjects.Size = new System.Drawing.Size(896, 219);
			this.dgDBObjects.TabIndex = 1;
			this.dgDBObjects.TableStyles.AddRange(new System.Windows.Forms.DataGridTableStyle[] {
            this.dataGridTableStyle1});
			this.dgDBObjects.DoubleClick += new System.EventHandler(this.dgDBObjects_DoubleClick);
			this.dgDBObjects.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.dgDBObjects_KeyPress);
			// 
			// cmObject
			// 
			this.cmObject.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.miCompare,
            this.miShow,
            this.miEdit,
            this.miSave,
            this.miCopy,
            this.menuItem2,
            this.cmnuObject,
            this.menuItem3,
            this.menuItem4});
			// 
			// miCompare
			// 
			this.miCompare.Index = 0;
			this.miCompare.Text = "Compare";
			this.miCompare.Click += new System.EventHandler(this.miCompare_Click);
			// 
			// miShow
			// 
			this.miShow.Index = 1;
			this.miShow.Text = "Show";
			this.miShow.Click += new System.EventHandler(this.miShow_Click);
			// 
			// miEdit
			// 
			this.miEdit.Index = 2;
			this.miEdit.Text = "Edit";
			this.miEdit.Click += new System.EventHandler(this.miEdit_Click);
			// 
			// miSave
			// 
			this.miSave.Index = 3;
			this.miSave.Text = "Save";
			this.miSave.Click += new System.EventHandler(this.miSave_Click);
			// 
			// miCopy
			// 
			this.miCopy.Index = 4;
			this.miCopy.Text = "Copy";
			this.miCopy.Click += new System.EventHandler(this.miCopy_Click);
			// 
			// menuItem2
			// 
			this.menuItem2.Index = 5;
			this.menuItem2.Text = "Remove";
			this.menuItem2.Click += new System.EventHandler(this.menuItem2_Click);
			// 
			// cmnuObject
			// 
			this.cmnuObject.Index = 6;
			this.cmnuObject.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.cmnuDepends,
            this.miShowVersions,
            this.miCreate,
            this.cmnuRename,
            this.miMakeSP,
            this.miShowSP,
            this.miTrace,
            this.cmnuDrop});
			this.cmnuObject.Text = "Object";
			// 
			// cmnuDepends
			// 
			this.cmnuDepends.Index = 0;
			this.cmnuDepends.Text = "Depends";
			this.cmnuDepends.Click += new System.EventHandler(this.cmnuDepends_Click);
			// 
			// miShowVersions
			// 
			this.miShowVersions.Index = 1;
			this.miShowVersions.Text = "Show (NN)s";
			this.miShowVersions.Click += new System.EventHandler(this.miShowVersions_Click);
			// 
			// miCreate
			// 
			this.miCreate.Index = 2;
			this.miCreate.Text = "Create";
			this.miCreate.Click += new System.EventHandler(this.miCreate_Click);
			// 
			// cmnuRename
			// 
			this.cmnuRename.Index = 3;
			this.cmnuRename.Text = "Rename";
			this.cmnuRename.Click += new System.EventHandler(this.cmnuRename_Click);
			// 
			// miMakeSP
			// 
			this.miMakeSP.Index = 4;
			this.miMakeSP.Text = "Make sp__";
			this.miMakeSP.Click += new System.EventHandler(this.miMakeSP_Click);
			// 
			// miShowSP
			// 
			this.miShowSP.Index = 5;
			this.miShowSP.Text = "Show sp__";
			this.miShowSP.Click += new System.EventHandler(this.miShowSP_Click);
			// 
			// miTrace
			// 
			this.miTrace.Index = 6;
			this.miTrace.Text = "Make Trace";
			this.miTrace.Click += new System.EventHandler(this.miTrace_Click);
			// 
			// cmnuDrop
			// 
			this.cmnuDrop.Index = 7;
			this.cmnuDrop.Text = "Drop";
			this.cmnuDrop.Click += new System.EventHandler(this.cmnuDrop_Click);
			// 
			// menuItem3
			// 
			this.menuItem3.Index = 7;
			this.menuItem3.Text = "Purge";
			this.menuItem3.Click += new System.EventHandler(this.menuItem3_Click);
			// 
			// menuItem4
			// 
			this.menuItem4.Index = 8;
			this.menuItem4.Text = "Folder";
			this.menuItem4.Click += new System.EventHandler(this.menuItem4_Click);
			// 
			// dataGridTableStyle1
			// 
			this.dataGridTableStyle1.AllowSorting = false;
			this.dataGridTableStyle1.DataGrid = this.dgDBObjects;
			this.dataGridTableStyle1.HeaderForeColor = System.Drawing.SystemColors.ControlText;
			this.dataGridTableStyle1.MappingName = "Objects";
			this.dataGridTableStyle1.ReadOnly = true;
			// 
			// txtTemplate
			// 
			this.txtTemplate.Location = new System.Drawing.Point(4, 24);
			this.txtTemplate.Name = "txtTemplate";
			this.txtTemplate.Size = new System.Drawing.Size(132, 20);
			this.txtTemplate.TabIndex = 0;
			this.txtTemplate.Text = "namespace";
			// 
			// txtServerFrom
			// 
			this.txtServerFrom.Location = new System.Drawing.Point(136, 24);
			this.txtServerFrom.Name = "txtServerFrom";
			this.txtServerFrom.Size = new System.Drawing.Size(68, 20);
			this.txtServerFrom.TabIndex = 1;
			this.txtServerFrom.Text = ((string)(configurationAppSettings.GetValue("txtServer.Text", typeof(string))));
			this.txtServerFrom.Validating += new System.ComponentModel.CancelEventHandler(this.txtServer_Validating);
			// 
			// label1
			// 
			this.label1.AutoSize = true;
			this.label1.Location = new System.Drawing.Point(140, 8);
			this.label1.Name = "label1";
			this.label1.Size = new System.Drawing.Size(64, 13);
			this.label1.TabIndex = 3;
			this.label1.Text = "Server From";
			// 
			// label2
			// 
			this.label2.AutoSize = true;
			this.label2.Location = new System.Drawing.Point(212, 8);
			this.label2.Name = "label2";
			this.label2.Size = new System.Drawing.Size(48, 13);
			this.label2.TabIndex = 3;
			this.label2.Text = "DB From";
			// 
			// label3
			// 
			this.label3.AutoSize = true;
			this.label3.Location = new System.Drawing.Point(420, 8);
			this.label3.Name = "label3";
			this.label3.Size = new System.Drawing.Size(38, 13);
			this.label3.TabIndex = 3;
			this.label3.Text = "DB To";
			// 
			// label4
			// 
			this.label4.AutoSize = true;
			this.label4.Location = new System.Drawing.Point(60, 8);
			this.label4.Name = "label4";
			this.label4.Size = new System.Drawing.Size(51, 13);
			this.label4.TabIndex = 3;
			this.label4.Text = "Template";
			// 
			// cmbDBFrom
			// 
			this.cmbDBFrom.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
			this.cmbDBFrom.Location = new System.Drawing.Point(208, 24);
			this.cmbDBFrom.Name = "cmbDBFrom";
			this.cmbDBFrom.Size = new System.Drawing.Size(132, 21);
			this.cmbDBFrom.TabIndex = 2;
			this.cmbDBFrom.Validating += new System.ComponentModel.CancelEventHandler(this.cmbDB_Validating);
			// 
			// cmbTo
			// 
			this.cmbTo.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
			this.cmbTo.Location = new System.Drawing.Point(412, 24);
			this.cmbTo.Name = "cmbTo";
			this.cmbTo.Size = new System.Drawing.Size(132, 21);
			this.cmbTo.TabIndex = 4;
			this.cmbTo.Validating += new System.ComponentModel.CancelEventHandler(this.cmbDB_Validating);
			// 
			// stBar
			// 
			this.stBar.Location = new System.Drawing.Point(0, 270);
			this.stBar.Name = "stBar";
			this.stBar.Panels.AddRange(new System.Windows.Forms.StatusBarPanel[] {
            this.spnlObjectName,
            this.spnlLeft});
			this.stBar.ShowPanels = true;
			this.stBar.Size = new System.Drawing.Size(896, 22);
			this.stBar.TabIndex = 5;
			// 
			// spnlObjectName
			// 
			this.spnlObjectName.Name = "spnlObjectName";
			this.spnlObjectName.Text = "Ready";
			this.spnlObjectName.Width = 200;
			// 
			// spnlLeft
			// 
			this.spnlLeft.AutoSize = System.Windows.Forms.StatusBarPanelAutoSize.Contents;
			this.spnlLeft.Name = "spnlLeft";
			this.spnlLeft.Width = 10;
			// 
			// btnRemEquals
			// 
			this.btnRemEquals.Location = new System.Drawing.Point(584, 24);
			this.btnRemEquals.Name = "btnRemEquals";
			this.btnRemEquals.Size = new System.Drawing.Size(76, 23);
			this.btnRemEquals.TabIndex = 0;
			this.btnRemEquals.Text = "Rem Equals";
			this.btnRemEquals.Click += new System.EventHandler(this.btnRemEquals_Click);
			// 
			// btnRefresh
			// 
			this.btnRefresh.Location = new System.Drawing.Point(660, 24);
			this.btnRefresh.Name = "btnRefresh";
			this.btnRefresh.Size = new System.Drawing.Size(76, 23);
			this.btnRefresh.TabIndex = 0;
			this.btnRefresh.Text = "Refresh";
			this.btnRefresh.Click += new System.EventHandler(this.btnRefresh_Click);
			// 
			// btmSave
			// 
			this.btmSave.Location = new System.Drawing.Point(740, 24);
			this.btmSave.Name = "btmSave";
			this.btmSave.Size = new System.Drawing.Size(75, 23);
			this.btmSave.TabIndex = 6;
			this.btmSave.Text = "&Save";
			this.btmSave.Click += new System.EventHandler(this.btmSave_Click);
			// 
			// btnOpen
			// 
			this.btnOpen.Location = new System.Drawing.Point(816, 24);
			this.btnOpen.Name = "btnOpen";
			this.btnOpen.Size = new System.Drawing.Size(75, 23);
			this.btnOpen.TabIndex = 6;
			this.btnOpen.Text = "&Open";
			this.btnOpen.Click += new System.EventHandler(this.btnOpen_Click);
			// 
			// chkPercsent
			// 
			this.chkPercsent.Checked = true;
			this.chkPercsent.CheckState = System.Windows.Forms.CheckState.Checked;
			this.chkPercsent.Location = new System.Drawing.Point(110, 8);
			this.chkPercsent.Name = "chkPercsent";
			this.chkPercsent.Size = new System.Drawing.Size(31, 13);
			this.chkPercsent.TabIndex = 7;
			this.chkPercsent.Text = "%";
			this.chkPercsent.CheckedChanged += new System.EventHandler(this.chkPercsent_CheckedChanged);
			// 
			// txtServerTo
			// 
			this.txtServerTo.Location = new System.Drawing.Point(340, 24);
			this.txtServerTo.Name = "txtServerTo";
			this.txtServerTo.Size = new System.Drawing.Size(68, 20);
			this.txtServerTo.TabIndex = 3;
			this.txtServerTo.Text = "SQL2005";
			this.txtServerTo.Validating += new System.ComponentModel.CancelEventHandler(this.txtServer_Validating);
			// 
			// label5
			// 
			this.label5.AutoSize = true;
			this.label5.Location = new System.Drawing.Point(340, 8);
			this.label5.Name = "label5";
			this.label5.Size = new System.Drawing.Size(54, 13);
			this.label5.TabIndex = 3;
			this.label5.Text = "Server To";
			// 
			// txtPath
			// 
			this.txtPath.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
									| System.Windows.Forms.AnchorStyles.Right)));
			this.txtPath.Location = new System.Drawing.Point(732, 1);
			this.txtPath.Name = "txtPath";
			this.txtPath.Size = new System.Drawing.Size(160, 20);
			this.txtPath.TabIndex = 8;
			this.txtPath.Text = "C:\\Data\\SQLDMO";
			// 
			// dlgPath
			// 
			this.dlgPath.Description = "Select folder for .sql files";
			this.dlgPath.SelectedPath = "C:\\Data\\MyDocs";
			// 
			// button1
			// 
			this.button1.Location = new System.Drawing.Point(704, 2);
			this.button1.Name = "button1";
			this.button1.Size = new System.Drawing.Size(22, 18);
			this.button1.TabIndex = 9;
			this.button1.Text = "...";
			this.button1.Click += new System.EventHandler(this.button1_Click);
			// 
			// btnAbort
			// 
			this.btnAbort.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
			this.btnAbort.ForeColor = System.Drawing.Color.Firebrick;
			this.btnAbort.Location = new System.Drawing.Point(548, 24);
			this.btnAbort.Name = "btnAbort";
			this.btnAbort.Size = new System.Drawing.Size(32, 20);
			this.btnAbort.TabIndex = 10;
			this.btnAbort.Text = "X";
			this.btnAbort.Click += new System.EventHandler(this.btnAbort_Click);
			// 
			// txtSchema
			// 
			this.txtSchema.Location = new System.Drawing.Point(548, 1);
			this.txtSchema.Name = "txtSchema";
			this.txtSchema.Size = new System.Drawing.Size(56, 20);
			this.txtSchema.TabIndex = 0;
			this.txtSchema.Text = "%";
			// 
			// label6
			// 
			this.label6.AutoSize = true;
			this.label6.Location = new System.Drawing.Point(526, 5);
			this.label6.Name = "label6";
			this.label6.Size = new System.Drawing.Size(22, 13);
			this.label6.TabIndex = 11;
			this.label6.Text = "NS";
			// 
			// txtType
			// 
			this.txtType.Location = new System.Drawing.Point(642, 2);
			this.txtType.Name = "txtType";
			this.txtType.Size = new System.Drawing.Size(56, 20);
			this.txtType.TabIndex = 0;
			this.txtType.Text = "%";
			// 
			// label7
			// 
			this.label7.AutoSize = true;
			this.label7.Location = new System.Drawing.Point(613, 4);
			this.label7.Name = "label7";
			this.label7.Size = new System.Drawing.Size(31, 13);
			this.label7.TabIndex = 11;
			this.label7.Text = "Type";
			// 
			// dlgSqlFiles
			// 
			this.dlgSqlFiles.Filter = "SQL files|*.sql";
			this.dlgSqlFiles.Multiselect = true;
			this.dlgSqlFiles.ShowReadOnly = true;
			this.dlgSqlFiles.Title = "Select File to pull together";
			// 
			// FormMain
			// 
			this.AcceptButton = this.btnConnect;
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.ClientSize = new System.Drawing.Size(896, 292);
			this.Controls.Add(this.label6);
			this.Controls.Add(this.btnAbort);
			this.Controls.Add(this.button1);
			this.Controls.Add(this.txtPath);
			this.Controls.Add(this.chkPercsent);
			this.Controls.Add(this.stBar);
			this.Controls.Add(this.label1);
			this.Controls.Add(this.txtTemplate);
			this.Controls.Add(this.txtServerFrom);
			this.Controls.Add(this.label2);
			this.Controls.Add(this.label3);
			this.Controls.Add(this.label4);
			this.Controls.Add(this.txtServerTo);
			this.Controls.Add(this.label5);
			this.Controls.Add(this.btmSave);
			this.Controls.Add(this.cmbDBFrom);
			this.Controls.Add(this.btnConnect);
			this.Controls.Add(this.cmbTo);
			this.Controls.Add(this.btnRemEquals);
			this.Controls.Add(this.btnRefresh);
			this.Controls.Add(this.btnOpen);
			this.Controls.Add(this.dgDBObjects);
			this.Controls.Add(this.txtSchema);
			this.Controls.Add(this.txtType);
			this.Controls.Add(this.label7);
			this.KeyPreview = true;
			this.Name = "FormMain";
			this.Text = "Form1";
			this.Load += new System.EventHandler(this.FormMain_Load);
			this.Closing += new System.ComponentModel.CancelEventHandler(this.FormMain_Closing);
			this.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.FormMain_KeyPress);
			((System.ComponentModel.ISupportInitialize)(this.dgDBObjects)).EndInit();
			((System.ComponentModel.ISupportInitialize)(this.spnlObjectName)).EndInit();
			((System.ComponentModel.ISupportInitialize)(this.spnlLeft)).EndInit();
			this.ResumeLayout(false);
			this.PerformLayout();

		}
		#endregion

		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main() {
			Application.Run(new FormMain());
		}
		#endregion

		#region Constants
		private const DMO.SQLDMO_OBJECT_TYPE DB_ALL_OBJECTS =
			DMO.SQLDMO_OBJECT_TYPE.SQLDMOObj_StoredProcedure |
			DMO.SQLDMO_OBJECT_TYPE.SQLDMOObj_Trigger |
			DMO.SQLDMO_OBJECT_TYPE.SQLDMOObj_UserTable |
			DMO.SQLDMO_OBJECT_TYPE.SQLDMOObj_View |
			DMO.SQLDMO_OBJECT_TYPE.SQLDMOObj_UserDefinedFunction |
			DMO.SQLDMO_OBJECT_TYPE.SQLDMOObj_UserDefinedDatatype;
		private const DMO.SQLDMO_SCRIPT_TYPE DB_SCRIPT_TYPE_ALL =
			DMO.SQLDMO_SCRIPT_TYPE.SQLDMOScript_PrimaryObject |
			DMO.SQLDMO_SCRIPT_TYPE.SQLDMOScript_DRI_All |
			DMO.SQLDMO_SCRIPT_TYPE.SQLDMOScript_Indexes;
		private const DMO.SQLDMO_SCRIPT_TYPE DB_SCRIPT_TYPE_ALL_CREATE = DB_SCRIPT_TYPE_ALL |
			DMO.SQLDMO_SCRIPT_TYPE.SQLDMOScript_Drops |
			DMO.SQLDMO_SCRIPT_TYPE.SQLDMOScript_Triggers;
			#region DB_SQL_CREATE_GET_OBJECTS_SP
		private const string DB_SQL_CREATE_GET_OBJECTS_SP = @"
DECLARE @SqlTempl varchar(8000)
DECLARE @SQL nvarchar(4000)
SET @SqlTempl = '
SELECT T1.name AS Name1,T2.name AS Name2,
ISNULL(T1.xtype,T2.xtype)+
	CASE WHEN ISNULL(T1.xtype,T2.xtype)<>ISNULL(T2.xtype,T1.xtype)THEN ''/''+ISNULL(T2.xtype,T1.xtype)ELSE ''''END AS XType
FROM 
(SELECT name,xtype FROM ~DBFrom~.dbo.sysobjects
WHERE RTRIM(xtype) NOT IN(''C'',''D'',''FN'',''IF'',''P'',''S'',''TF'',''TR'',''V'') AND name LIKE @Name
UNION ALL
SELECT so.name, so.xtype
FROM ~DBFrom~.dbo.syscomments sc INNER JOIN ~DBFrom~.dbo.sysobjects so ON sc.id = so.id
WHERE RTRIM(xtype) IN (''C'',''D'',''FN'',''IF'',''P'',''TF'',''TR'',''V'') AND (sc.text LIKE N''' + @Name + ''')
UNION ALL
SELECT name,''DT'' FROM ~DBFrom~.dbo.systypes WHERE usertype > 256 AND name LIKE @Name
UNION ALL
SELECT so.name,''U''
FROM ~DBFrom~.dbo.syscolumns sc INNER JOIN ~DBFrom~.dbo.sysobjects so ON sc.id = so.id WHERE sc.name LIKE @Name AND so.xtype = ''U ''
)T1 ~JOIN~
(SELECT name ,xtype FROM ~DBTo~.dbo.sysobjects
WHERE RTRIM(xtype) NOT IN(''C'',''D'',''FN'',''IF'',''P'',''S'',''TF'',''TR'',''V'') AND name LIKE @Name
UNION ALL
SELECT so.name, so.xtype
FROM ~DBTo~.dbo.syscomments sc INNER JOIN ~DBTo~.dbo.sysobjects so ON sc.id = so.id
WHERE RTRIM(xtype) IN (''C'',''D'',''FN'',''IF'',''P'',''TF'',''TR'',''V'') AND (sc.text LIKE N''' + @Name + ''')
UNION ALL
SELECT name,''DT'' FROM ~DBTo~.dbo.systypes WHERE usertype > 256 AND name LIKE @Name
UNION ALL
SELECT so.name,''U''
FROM ~DBTo~.dbo.syscolumns sc INNER JOIN ~DBTo~.dbo.sysobjects so ON sc.id = so.id WHERE sc.name LIKE @Name AND so.xtype = ''U ''
)T2'

DECLARE @T2 varchar(8000) SET @T2 = '(SELECT TOP 0 '''' name,''''xtype)T2'

IF @DBFrom = @DBTo BEGIN
	SET @SqlTempl = SUBSTRING(@SqlTempl,1,PATINDEX('%~JOIN~%',@SqlTempl)-1)+' ~JOIN~ '+@T2
END

SET @SqlTempl = @SqlTempl+' ON T1.name = t2.name
'

SET @SQL = '
SELECT ISNULL(Name1,'''') AS NameFrom,ISNULL(Name2,'''') AS NameTo,XType AS Type
			 --,CASE TEXT1.text WHEN TEXT2.text THEN 1 ELSE 0 END AS Equal
			 ,'''' AS TextFrom,'''' AS TextTo
			 --ISNULL(TEXT1.Text,'''') AS TextFrom,ISNULL(TEXT2.Text,'''') AS TextTo
FROM (
SELECT DISTINCT Name1,Name2,XType FROM (
'+REPLACE(@SqlTempl,'~JOIN~','LEFT OUTER JOIN')+
'
UNION ALL
'+REPLACE(@SqlTempl,'~JOIN~','RIGHT OUTER JOIN')+
'
)T3
)T4
LEFT OUTER JOIN
(SELECT so.name, REPLACE(REPLACE(REPLACE(REPLACE(ISNULL(sc.text,''''),'' '',''''),CHAR(10),''''),CHAR(13),''''),CHAR(9),'''') text
 FROM ~DBFrom~.dbo.syscomments sc INNER JOIN ~DBFrom~.dbo.sysobjects so ON sc.id = so.id
 WHERE xtype <> ''U ''
)TEXT1 ON T4.Name1 = TEXT1.name
LEFT OUTER JOIN
(SELECT so.name, REPLACE(REPLACE(REPLACE(REPLACE(ISNULL(sc.text,''''),'' '',''''),CHAR(10),''''),CHAR(13),''''),CHAR(9),'''') text
 FROM ~DBTo~.dbo.syscomments sc INNER JOIN ~DBTo~.dbo.sysobjects so ON sc.id = so.id
 WHERE xtype <> ''U ''
)TEXT2 ON T4.Name2 = TEXT2.name

'

SET @SQL = REPLACE(REPLACE(@SQL,'~DBTo~',@DBTo),'~DBFrom~',@DBFrom)

EXEC sp_ExecuteSQL @SQL,N'@Name sysname',@Name
";
		#endregion
		#endregion

		#region Properties
		private string PersistFileName{get{return AppDomain.CurrentDomain.FriendlyName+".xml";}}
		private bool dontRestore = false;
		private Thread thrFetchText = null;
		private string StatusObject { set { txtPath.Invoke(new Action(() => spnlObjectName.Text = value)); } }
		private string StatusLeft { set { txtPath.Invoke(new Action(() => spnlLeft.Text = value)); } }
		private StringList NonScriptableTypes{get{return new StringList("D,F,PK");}}
		private DBObjectsDS dsDBObjects = new DBObjectsDS();
		private DataView dvDBObjects = null;
		private string Path{get{return txtPath.Invoke(new Func<string>(() => txtPath.Text))+"";}}
		private string ServerFrom{
			get{return txtPath.Invoke(new Func<string>(() => txtServerFrom.Text))+"";}
			set{txtServerFrom.Text = value;}
		}
		private string ServerTo{
			get{return txtPath.Invoke(new Func<string>(() => txtServerTo.Text))+"";}
			set{txtServerTo.Text = value;}
		}
		private string DBFrom{
			get{return txtPath.Invoke(new Func<string>(() => cmbDBFrom.Text))+"";}
			set{cmbDBFrom.Text = value;}
		}
		private string DBTo{
			get{return txtPath.Invoke(new Func<string>(() => cmbTo.Text))+"";}
			set{cmbTo.Text = value;}
		}
		private string DBTemplate{
			get{return txtPath.Invoke(new Func<string>(() => txtTemplate.Text))+"";}
			set{txtTemplate.Text = value;}
		}
		private DataGrid dgDBObjectsGrid { get { return txtPath.Invoke(new Func<DataGrid>(() => dgDBObjects)) as DataGrid; } }
		//Ssms.exe
		private static string StudioName { get { return ConfigurationSettings.AppSettings["StudioName"]; } }
		private string GetConn(string serverName, string dbName) {
			return ConfigurationSettings.AppSettings["Conn"].Replace("~DBServer~", serverName).Replace("~DBName~", dbName);
		}
		private string GetConnCurr() { return GetConn(CurrentServerName, CurrentDBName); }
		private string GetConnFrom(string dbName){
			return ConfigurationSettings.AppSettings["Conn"].Replace("~DBServer~",ServerFrom).Replace("~DBName~",dbName);
		}
		private string GetConnTo(string dbName){
			return ConfigurationSettings.AppSettings["Conn"].Replace("~DBServer~",ServerTo).Replace("~DBName~",dbName);
		}
		private string CurrentServerName{
			get{
				int col = dgDBObjects.CurrentCell.ColumnNumber;
				string colName = dgDBObjects.TableStyles[0].GridColumnStyles[col].MappingName;
				if( colName.IndexOf("Name") != 0 )
					throw new Exception("Invalid column["+colName+"]!");
				return colName.ToLower().IndexOf("from") >= 0 ? ServerFrom : ServerTo;
			}
		}
		private string CurrentServerFrom{get{return CurrentServerName;}}
		private string CurrentServerTo{get{return CurrentServerFrom == ServerFrom ? ServerTo : ServerFrom;}}
		private string CurrentPath{get{return IO.Path.Combine(Path,CurrentServerName)+"\\"+CurrentDBName;}}
		
		private string CurrentDBName{
			get{
				int col = dgDBObjects.CurrentCell.ColumnNumber;
				string colName = dgDBObjects.TableStyles[0].GridColumnStyles[col].MappingName;
				if( colName.IndexOf("Name") != 0 )
					throw new Exception("Invalid column["+colName+"]!");
				return colName.ToLower().IndexOf("from") >= 0 ? DBFrom : DBTo;
			}
		}
		private string CurrentDBFrom{get{return CurrentDBName;}}
		private string CurrentDBTo{get{return CurrentDBFrom == DBFrom ? DBTo : DBFrom;}}

		private string[] CurrentObjectNames {
			get {
				StringList slNames = new StringList();
				foreach (DBObjectsDS.ObjectsRow row in CurrentObjectsRows)
					slNames.Add(row["Schema"] + ".[" + row[dgDBObjects.CurrentCell.ColumnNumber] + "]");
				if (slNames.Count == 0) slNames.Add(CurrentObjectName);
				return slNames;
			}
		}
		private NameValueCollection GetObjectsList() {
			NameValueCollection nvcInfo = new NameValueCollection();
			foreach (DataRowView row in DataGridView)
				nvcInfo.Add(row["Schema"] + ".[" + row[dgDBObjects.CurrentCell.ColumnNumber] + "]",row["TextFrom"]+"");
			return nvcInfo;
		}
		private string CurrentObjectName {
			get{return CurrentObjectsRow["Schema"]+".["+CurrentObjectsRow[dgDBObjects.CurrentCell.ColumnNumber]+"]";}
			set{CurrentObjectsRow[dgDBObjects.CurrentCell.ColumnNumber] = value;}
		}

		private DBObjectsDS.ObjectsRow[] CurrentObjectsRows{
			get{
				ArrayList alCells = new ArrayList();
				foreach( int i in SelectedRows() )
					alCells.Add(DataGridView[i].Row);
				if( alCells.Count == 0 )alCells.Add(CurrentObjectsRow);
				return (DBObjectsDS.ObjectsRow[])alCells.ToArray(typeof(DBObjectsDS.ObjectsRow));
			}
		}
		private DBObjectsDS.ObjectsRow CurrentObjectsRow{
			get{
				return (DBObjectsDS.ObjectsRow)(((DataView)dgDBObjects.DataSource)[dgDBObjects.CurrentCell.RowNumber].Row);
			}
		}

		private int[] SelectedRows(){
			int rc = RowsCount;
			ArrayListEx alRows = new ArrayListEx();
			for( int i=0; i < rc; i++ )
				if( dgDBObjects.IsSelected(i) )alRows.Add(i);
			return alRows;
		}
		private int RowsCount{get{return ((DataView)dgDBObjects.DataSource).Count;}}
		private DataView DataGridView{get{return (DataView)dgDBObjects.DataSource;}}
		#endregion

		#region Fill DataGrid
		private void ListDBObject(){
			StopFetchText();
			dsDBObjects.Objects.Clear();
			try{
				dsDBObjects.Objects.PrimaryKey = null;
				SQLHelperEx.ExecuteDatasetEx(GetConnFrom(DBFrom),dsDBObjects.Objects,SqlConstants.DB_SQL_GET_OBJECTS,DBTemplate.Replace("_","[_]"),txtSchema.Text,txtType.Text);
					if( ServerTo != "" ){
					DBObjectsDS dsTo = new DBObjectsDS();
					SQLHelperEx.ExecuteDatasetEx(GetConnTo(DBTo),dsTo.Objects,SqlConstants.DB_SQL_GET_OBJECTS,DBTemplate.Replace("_","[_]"),txtSchema.Text,txtType.Text);
					DBObjectsDS.ObjectsDataTable dtObjects = dsDBObjects.Objects;
					foreach( DBObjectsDS.ObjectsRow row in dsTo.Objects ){
						DBObjectsDS.ObjectsRow[] rows = (DBObjectsDS.ObjectsRow[])dtObjects.Select("NameFrom='"+row.NameFrom+"'");
						if( rows.Length != 0 ){
							rows[0].NameTo = row.NameFrom;
							rows[0].TextTo = row.TextFrom;
							rows[0].MSS_To = row.MSS;
						}
						else dtObjects.AddObjectsRow("",row.NameFrom,row.Type,false,"",row.TextFrom,0,row.MSS,row.Schema,false);
					}
				}
			}catch(SqlException exc){
				MessageBox.Show(ClientException.GetMessages(exc));
			}
			SetDataSource();
		}
		private void SetDataSource(DBObjectsDS dsDBObjects){
			this.dsDBObjects = dsDBObjects;
			SetDataSource();
		}
		private void SetDataSource(){
			StopFetchText();
			dvDBObjects = dsDBObjects.Objects.DefaultView;
			dvDBObjects.Sort = "Type,NameFrom"+(dsDBObjects.Objects.Columns.Contains("NameTo")?",NameTo":"");
			//DataGridTableStyle ts = new DataGridTableStyle();
			//ts.MappingName = "Objects";
			//dgDBObjects.TableStyles.Add(ts);
			dgDBObjects.DataSource = dvDBObjects;
			StartFetchText();
		}
		private void StartFetchText(){
			//FetchText();
			(thrFetchText = new Thread(new ThreadStart(FetchText))).Start();
		}
		private void StopFetchText(){ if(thrFetchText != null && thrFetchText.IsAlive)thrFetchText.Abort();}
		private void FetchText(){
			using(SQLDMONET dmoFrom = new SQLDMONET(ServerFrom)){
				using(SQLDMONET dmoTo = new SQLDMONET(ServerTo)){
					//foreach( DBObjectsDS.ObjectsRow row in dsDBObjects.Objects )
					//	row.Equal = row.NameFrom == row.NameTo && CompareObjects(row.TextFrom,row.TextTo);
					int count = 0;
					do{
						DataRow[] rows = dsDBObjects.Objects.Select("Type IN('U ','DT') OR TextFrom='' OR (NameTo>'' AND TextTo='')");
						count = rows.Length;
						try{
							foreach(DBObjectsDS.ObjectsRow row in rows){
								StatusObject = row.NameFrom + "/" + row.NameTo;
								StatusLeft = count-- + " left";
								Application.DoEvents();
								if( !NonScriptableTypes.Contains(row.Type.Trim()) ){
									try{
										if( row.TextFrom == "" )row.TextFrom = dmoFrom.ObjectText(Path,DBFrom,row.Schema+".["+row.NameFrom+"]",DB_SCRIPT_TYPE_ALL,m,false);
										if( row.TextTo == "" )row.TextTo = dmoTo.ObjectText(Path,DBTo,row.Schema+".["+row.NameTo+"]",DB_SCRIPT_TYPE_ALL,m,false);
									}catch(ThreadAbortException){return;
									}catch(Exception exc){MessageBox.Show(this,ClientException.GetExceptions(exc));}
									row.Equal = row.NameFrom == row.NameTo && row.MSS == row.MSS_To && CompareObjects(row.TextFrom,row.TextTo);
								}else
									row.Equal = row.NameFrom == row.NameTo;
							}
							count = 0;
						}catch( ThreadAbortException ){
							return;
						}catch( InvalidOperationException ){
							return;
						}catch(Exception exc){
							MessageBox.Show(ClientException.GetMessages(exc));
							return;
						}
					}while( count-- > 0 );
				}
			}
			SetColumns();
			StatusObject = "Ready";
		}
		private bool CompareObjects(string text1,string text2){
			string exp = @"\s*--\s*(Version\s*\d+[.]\d*,)?\s*Created On\s+\w{3}\s+\d+\s+\d{4}\s+\d+:\d+[AP]M";
			text1 = Regex.Replace(text1,exp,""); text2 = Regex.Replace(text2,exp,"");
			exp = "[dbo].";	text1 = text1.Replace(exp,"");	text2 = text2.Replace(exp,"");
			exp = " dbo.";	text1 = text1.Replace(exp,"");	text2 = text2.Replace(exp,"");
			exp = "ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]";text1 = text1.Replace(exp,"ON [PRIMARY]");text2 = text2.Replace(exp,"ON [PRIMARY]");
			exp = @"[\[\]\s]";text1 = Regex.Replace(text1,exp,"");text2 = Regex.Replace(text2,exp,"");
			
			exp = @"\((?<num>\d+)\)";
			text1 = Regex.Replace(text1,exp,"${num}");
			text2 = Regex.Replace(text2,exp,"${num}");
			
			exp = "((";text1 = text1.Replace(exp,"(");	text2 = text2.Replace(exp,"(");
			exp = "))";text1 = text1.Replace(exp,")");	text2 = text2.Replace(exp,")");
			return Regex.IsMatch(text1,"^"+ Regex.Escape(text2)+"$",RegexOptions.IgnoreCase);
		}
		private void SetColumns(){
			bool hasTo = false;
			foreach( DBObjectsDS.ObjectsRow row in dsDBObjects.Objects )
				if( row.RowState != DataRowState.Deleted && (hasTo = !(row.IsNameToNull() || row.NameTo == "")) )break;
			var styles = dgDBObjectsGrid.TableStyles[0].GridColumnStyles;
			this.Invoke(new Action(() => {
				styles["NameTo"].Width = hasTo ? styles["NameFrom"].Width : 0;
				styles["TextTo"].Width = hasTo ? styles["TextFrom"].Width : 0;
				styles["Equal"].Width = hasTo ? 35 : 0;
			}));
		}
		#endregion

		#region Event Handlers

		#region FormMain
		private void FormMain_Load(object sender, System.EventArgs e) {
			txtServerFrom.Tag = cmbDBFrom;
			txtServerTo.Tag = cmbTo;
			if( !dontRestore )Restore("");
			if( dsDBObjects.Persist.Count == 1 ){
				ServerFrom = dsDBObjects.Persist[0].ServerFrom;
				ServerTo = dsDBObjects.Persist[0].ServerTo;
			}
			if( ServerFrom == "" )return;
			FillDBList(ServerFrom,cmbDBFrom);
			FillDBList(ServerTo,cmbTo);
			if( dsDBObjects.Persist.Count == 1 ){
				DBFrom = dsDBObjects.Persist[0].DBFrom;
				DBTo = dsDBObjects.Persist[0].DBTo;
			}
			if( dsDBObjects.Objects.Count > 0 )SetDataSource();
		}
		private void FormMain_Closing(object sender, System.ComponentModel.CancelEventArgs e) {
			if( !dontRestore )Persist("");
		}
		private void FormMain_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e) {
			if( e.KeyChar == 14 )//Ctrl/n
				(new FormMain(ServerFrom,ServerTo,DBFrom,DBTo,DBTemplate,null)).ShowDialog(this);
		}
		#endregion

		#region Buttons
		private void btnConnect_Click(object sender, System.EventArgs e) {
			try{
				SetDBTemplate();
				ListDBObject();
			}catch(Exception exc){ MessageBox.Show(ClientException.GetMessages(exc)); }
		}

		private void btnRemEquals_Click(object sender, System.EventArgs e) {
			foreach( DBObjectsDS.ObjectsRow row in dsDBObjects.Objects.Select("Equal=1") )
				row.Delete();
			dsDBObjects.AcceptChanges();
		}
		private void btnRefresh_Click(object sender, System.EventArgs e) {
			foreach( DBObjectsDS.ObjectsRow row in dsDBObjects.Objects )
				row.TextFrom = row.TextTo = "";
			StartFetchText();
		}

		private void btmSave_Click(object sender, System.EventArgs e) {
			try{
				var objectsList = new List<string>();
				var rows = dsDBObjects.Objects.Select(r => r["TextFrom"]+"");
				foreach (var row in rows)
					objectsList.Add(row);
				File.WriteAllText("C:\\Motobank.sql", string.Join(Environment.NewLine, objectsList.ToArray()));
				Persist();
			}catch(Exception exc){ MessageBox.Show(ClientException.GetMessages(exc)); }
		}
		private void btnOpen_Click(object sender, System.EventArgs e) {
			try{
				Restore();
			}catch(Exception exc){ MessageBox.Show(ClientException.GetMessages(exc)); }
		}
		#endregion

		#region Context Menu
		private void miMakeSP_Click(object sender, System.EventArgs e) {
			StringList slObjectNames = new StringList();
			foreach( string on in CurrentObjectNames ){
				SQLHelperEx.ExecuteNonQueryEx(GetConnCurr(),"EXEC sp_MS_marksystemobject '"+on+"'");
				continue;
				string objectName = Regex.Replace(on,"^sp__","",RegexOptions.IgnoreCase);
				using(SQLDMONET dmo = new SQLDMONET(CurrentServerName)){
					string fileName = dmo.ObjectText(Path,CurrentDBName,objectName,"",true);
					if( fileName != "" )slObjectNames.Add(SQLDMONET.MakeSP___Compliant(fileName));
				}
				string sql = SQLHelperEx.ExecuteScalarEx(GetConnCurr(),"_MakeSP___",objectName,1)+"";
				objectName = "sp__"+objectName;
				slObjectNames.Add(SQLDMONET.SaveSqlToFile(sql,Path,CurrentServerName,CurrentDBName,objectName));
			}
			return;
			ShowFileInQueryAnalyzer(CurrentServerName,CurrentDBName,(string[])slObjectNames);
		}

		private void miShowSP_Click(object sender, System.EventArgs e) {
			StringList slObjectNames = new StringList();
			foreach( string on in CurrentObjectNames ){
				string objectName = Regex.Replace(on,"^sp__","",RegexOptions.IgnoreCase);
				slObjectNames.Add(objectName);
				slObjectNames.Add("sp__"+objectName);
			}
			ShowQueryAnalyzer(CurrentServerName,CurrentDBName,(string[])slObjectNames);
		}

		private void miShowVersions_Click(object sender, System.EventArgs e) {
			foreach( string objectName in CurrentObjectNames ){
				string fileName = SQLDMONET.BuildSqlFileName(Path,CurrentServerName,CurrentDBName,objectName);
				StringList sl = FileManager.GetFileVersions(fileName,"(??)");
				sl.Insert(0,fileName);
				ShowFileInQueryAnalyzer(CurrentServerName,CurrentDBName,(string[])sl);
			}
		}

		private void miTrace_Click(object sender, System.EventArgs e) {
			StringList fileNames = new StringList();
			foreach( string objectName in CurrentObjectNames )
				fileNames.Add(FileManager.GetFileFromBytes(MakeTrace(CurrentServerName,CurrentDBName,objectName),".sql",false));
			ShowFileInQueryAnalyzer(CurrentServerName,CurrentDBName,(string[])fileNames);
		}
		private void menuItem4_Click(object sender, System.EventArgs e) {
			string NL = Environment.NewLine;
			string s = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
			if( dlgSqlFiles.InitialDirectory == "" )dlgSqlFiles.InitialDirectory = txtPath.Text;
			if( dlgSqlFiles.ShowDialog(this) != DialogResult.OK )return;
			string fileTemp = FileManager.BuildFullFileName("SQLDMO","sql",false);
			File.Create(fileTemp).Close();
			StreamWriter sw = File.AppendText(fileTemp);
			sw.WriteLine("BEGIN TRAN");
			foreach( string fileName in dlgSqlFiles.FileNames )
				sw.Write(NL+"PRINT '*=======* ["+fileName+"] *======*'"+NL+"GO"+NL+FileManager.GetTextFromFile(fileName));
			sw.WriteLine(Environment.NewLine+"GO"+Environment.NewLine+"ROLLBACK TRAN");
			sw.Close();
			ShowFileInQueryAnalyzer(CurrentServerName,CurrentDBName,fileTemp);
		}

		private void btnAbort_Click(object sender, System.EventArgs e) {
			StopFetchText();
		}

		private void miShow_Click(object sender, System.EventArgs e) {
			foreach( string fileName in GetObjectFiles(CurrentServerName,CurrentDBName,CurrentObjectNames,false) )
				Process.Start("notepad.exe",fileName);
		}
		private void miCopy_Click(object sender, System.EventArgs e) {
			StringList slFiles = new StringList();
			foreach( string objectName in CurrentObjectNames )
				slFiles.Add(CopyObject(CurrentServerFrom,CurrentServerTo,CurrentDBFrom,CurrentDBTo,objectName));
			ShowFileInQueryAnalyzer(CurrentServerTo,CurrentDBTo,(string[])slFiles);
		}
		private string CopyObject(string serverFrom,string serverTo,string dbFrom,string dbTo,string objectName){
			try{
				using(SQLDMONET dmoFrom = new SQLDMONET(serverFrom)){
					using(SQLDMONET dmoTo = new SQLDMONET(serverTo)){
						DMO.DBObject dboTo = dmoTo.Object(dbTo,GetObjectName(objectName),GetObjectSchema(objectName));
						bool destObjectExists = dboTo != null && dboTo.Type != DMO.SQLDMO_OBJECT_TYPE.SQLDMOObj_UserTable;
						string fileName =	SQLDMONET.BuildSqlFileName(Path,serverTo,dbTo,objectName);
						if( destObjectExists )
								dmoTo.ObjectText(Path,dbTo,objectName,SQLDMONET.DB_SCRIPT_TYPE_ALL_CREATE,"",false);
						return SQLDMONET.SaveSqlToFile(
							dmoFrom.ObjectText(Path,dbFrom,objectName,destObjectExists? SQLDMONET.DB_SCRIPT_TYPE_ALL :SQLDMONET.DB_SCRIPT_TYPE_ALL_CREATE,m,destObjectExists),
							fileName);
					}
				}
			}catch(Exception exc){
				MessageBox.Show(ClientException.GetExceptions(exc));
				return "";
			}
		}
		private void miCompare_Click(object sender, System.EventArgs e) {
			ShowDifference(ServerFrom,ServerTo,DBFrom,DBTo,CurrentObjectName);
		}
		private void cmnuDepends_Click(object sender, System.EventArgs e) {
			try{
				GetDepends(CurrentServerFrom, CurrentDBFrom,CurrentObjectName);
			}catch(Exception exc){ MessageBox.Show(ClientException.GetMessages(exc)); }
		}
		private void cmnuDrop_Click(object sender, System.EventArgs e) {
			try{
				using(SQLDMONET dmo = new SQLDMONET(CurrentServerName)){
					ShowQueryAnalyzer(CurrentServerName,CurrentDBName,CurrentObjectNames);
					if( MessageBox.Show(this,"Drop objects "+CurrentServerName+"."+CurrentDBName+"."+string.Join(",",CurrentObjectNames)+"?","Drop object from DB",MessageBoxButtons.OKCancel) != DialogResult.OK )return;
					foreach( string on in CurrentObjectNames )
						dmo.Object(CurrentDBName,GetObjectName(on),GetObjectSchema(on)).Remove();
					MessageBox.Show(this,"Removed!");
				}
			}catch(Exception exc){ MessageBox.Show(ClientException.GetMessages(exc)); }
		}
		private void cmnuRename_Click(object sender, System.EventArgs e) {
			try{
				using(SQLDMONET dmo = new SQLDMONET(ServerFrom)){
					Rename rf = new Rename("New Name:",CurrentObjectName);
					if( rf.ShowDialog(this) == DialogResult.OK ){
						dmo.Object(CurrentDBName,GetObjectName(CurrentObjectName),GetObjectSchema(CurrentObjectName)).Name = rf.Value;
						CurrentObjectName = rf.Value;
					}
					rf.Dispose();
				}
			}catch(Exception exc){ MessageBox.Show(ClientException.GetMessages(exc)); }
		}
		private void menuItem3_Click(object sender, System.EventArgs e) {
			CleanSqlFiles(CurrentPath,2);
		}
		private void miEdit_Click(object sender, System.EventArgs e) {
			ShowQueryAnalyzer(CurrentServerName,CurrentDBName,CurrentObjectNames,true);
		}
		private void miSave_Click(object sender, EventArgs e) {
			NameValueCollection nvcObjects = GetObjectsList();
			if(dlgPath.ShowDialog(this) != DialogResult.OK )return;
			foreach( string fileName in nvcObjects.AllKeys )
				try {
					IO.File.WriteAllText(IO.Path.Combine(dlgPath.SelectedPath, fileName.Replace("]", "").Replace("[", "") + ".sql"), nvcObjects[fileName]);
				} catch (Exception exc) {
					MessageBox.Show(this, fileName, exc.Message);
				}
		}
		private void miCreate_Click(object sender, System.EventArgs e) {
			ShowQueryAnalyzer(CurrentServerName,CurrentDBName,CurrentObjectNames);
		}
		private void menuItem2_Click(object sender, System.EventArgs e) {
			try{RemoveRows();
			}catch(Exception exc){ MessageBox.Show(ClientException.GetMessages(exc)); }
		}
		private void chkPercsent_CheckedChanged(object sender, System.EventArgs e) {
			SetDBTemplate();		
		}
		private void button1_Click(object sender, System.EventArgs e){
			string s = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
			if( dlgPath.SelectedPath == s )dlgPath.SelectedPath = txtPath.Text;
			if( dlgPath.ShowDialog(this) != DialogResult.OK )return;
			txtPath.Text = dlgPath.SelectedPath;
		}
		private void txtServer_Validating(object sender, System.ComponentModel.CancelEventArgs e) {
			TextBox tb = (TextBox)sender;
			ComboBox cb = (ComboBox)tb.Tag;
			string db = cb.SelectedItem + "";
			if( tb.Modified ){
				e.Cancel = !FillDBList(tb.Text,cb);
				if( !e.Cancel )cb.SelectedItem = db;
			}
			tb.Modified = false;
		}

		private void cmbDB_Validating(object sender, System.ComponentModel.CancelEventArgs e) {
			e.Cancel = ServerFrom.ToLower() == ServerTo.ToLower() && DBFrom == DBTo;
		}
		#endregion

		#region dgDBObjects
		private void dgDBObjects_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e) {
			if( e.KeyChar.ToString().ToLower() == "d" )RemoveRows();
		}
		private void dgDBObjects_DoubleClick(object sender, System.EventArgs e) {
			DataGridTableStyle ts = dgDBObjects.TableStyles["Objects"];
			if( ts.GridColumnStyles["NameTo"].Width == 0 )return;
			int width = Math.Max(ts.GridColumnStyles["NameFrom"].Width,ts.GridColumnStyles["NameTo"].Width);
			ts.GridColumnStyles["NameFrom"].Width = ts.GridColumnStyles["NameTo"].Width = width;
		}
		#endregion
		
		#endregion

		#region Persist/Restore
		private SaveFileDialog sf = new SaveFileDialog();
		private OpenFileDialog of = new OpenFileDialog();
		private void Restore(){
			of.FileName = sf.FileName;
			of.Filter = "XML files|*.xml";
			if( of.ShowDialog(this) == DialogResult.Cancel || of.FileName == "" )return;
			Restore(of.FileName);
			SetDataSource();
		}
		private void Restore(string fileName){
			if( fileName == "" )fileName = PersistFileName;
			if( !File.Exists(fileName) )return;
			dsDBObjects.ReadXml(fileName,XmlReadMode.Auto);
			ServerFrom = dsDBObjects.Persist[0].ServerFrom;
			ServerTo = dsDBObjects.Persist[0].ServerTo;
			DBFrom = dsDBObjects.Persist[0].DBFrom;
			DBTo = dsDBObjects.Persist[0].DBTo;
			DBTemplate= dsDBObjects.Persist[0].Filter;
		}
		private void Persist(){
			sf.DefaultExt = ".xml";
			sf.Title = "Persist current state in XML file";
			sf.Filter = "XML files|*.xml";
			sf.FileName = DBFrom+"-"+DBTo+"("+GetTemplate(DBTemplate)+")";
			if( sf.ShowDialog(this) == DialogResult.Cancel || sf.FileName == "" )return;
			Persist(sf.FileName);
		}
		private void Persist(string fileName){
			if( fileName == "" )fileName = PersistFileName;
			FillPersistTable();
			dsDBObjects.WriteXml(fileName,XmlWriteMode.WriteSchema);
		}
		private void FillPersistTable(){FillPersistTable(ServerFrom,ServerTo,DBFrom,DBTo,DBTemplate);}
		private void FillPersistTable(string serverFrom,string serverTo,string dbFrom,string dbTo,string dbTemplate){
			dsDBObjects.Persist.Clear();
			dsDBObjects.Persist.AddPersistRow(serverFrom,serverTo,dbFrom,dbTo,dbTemplate);
		}
		#endregion

		#region Helpers
		private string MakeTrace(string serverName,string dbName,string objectName){ 
			string text = SQLDMONET.ObjectText(serverName,dbName,objectName,true);
			string trace = "/*T*/";//"-- [TRACE] --";
			string anchor = Regex.Escape(trace);
			string tableName = SQLHelperEx.ExecuteScalarEx(GetConn(serverName,dbName),"SELECT dbo.fn_TriggerTable(@TN)",objectName)+"";
			string SQL_TRACE = trace+"IF dbo.Config_Trace() = 1 BEGIN SELECT * INTO #inserted FROM inserted DECLARE @CU varbinary(999) SET @CU=COLUMNS_UPDATED()EXEC sp__TraceTrigger @@PROCID,@CU END"+trace;
			//"/*T*/IF dbo.Config_Trace() = 1 BEGIN DECLARE @CU varbinary(999) SET @CU=COLUMNS_UPDATED() EXEC sp__TraceTrigger @@PROCID,@CU END/*T*/";
			
			text = Regex.IsMatch(text,anchor+@"[\s\S]*"+anchor) ? Regex.Replace(text,anchor+@"[\s\S]*"+anchor,SQL_TRACE) : text+SQL_TRACE;
			return text;
		}
		private void CleanSqlFiles(string folder,int count){
			StringList files = FileManager.GetFileVersions(folder+"\\*.sql");
			foreach( string file in files ){
				int ver = int.Parse(FileManager.GetFileVersion(file,"(00)"));
				if( ver > count )File.Delete(file);
			}
		}
		private bool FillDBList(string server,ComboBox combo){
			string[] dbs = new SQLDMONET(server).Databases;
			combo.DataSource = dbs;
			return dbs.Length > 0 || server == "";
		}
		private void ShowDifference(string server1,string server2,string dbName1,string dbName2,string objectName){
			try{
				using( SQLDMONET dmo1 = new SQLDMONET(server1) ){
					using( SQLDMONET dmo2 = new SQLDMONET(server2) ){
						string fromText = dmo1.ObjectText(Path,dbName1,objectName,"",false);
						string toText =  server1 != server2 || dbName1 != dbName2 ? dmo2.ObjectText(Path,dbName2,objectName,"",false) : "";
						if( fromText != "" && toText != "" )
							Process.Start(@"WinDiff.Exe",fromText+" "+toText);
						else if(fromText != "")
							ShowFileInQueryAnalyzer(server1,dbName1,fromText);
						else
							ShowFileInQueryAnalyzer(server2,dbName2,toText);
					}
				}
			}catch(Exception exc){ MessageBox.Show(ClientException.GetMessages(exc)); }
		}
		private string[] GetObjectFiles(string server,string dbName,string[] objectNames,bool alter){
			StringList slFiles = new StringList();
			using(SQLDMONET dmo = new SQLDMONET(server))
				foreach( string objectName in objectNames )
					slFiles.Add(dmo.ObjectText(Path,dbName,objectName,alter?SQLDMONET.DB_SCRIPT_TYPE_ALL:SQLDMONET.DB_SCRIPT_TYPE_ALL_CREATE,"",alter));
			return slFiles;
		}
		private void ShowQueryAnalyzer(string server,string dbName,string objectName){
			ShowQueryAnalyzer(server,dbName,new string[]{objectName});
		}
		private void ShowQueryAnalyzer(string server,string dbName,string[] objectNames){
			ShowQueryAnalyzer(server,dbName,objectNames,false);
		}
		private void ShowQueryAnalyzer(string server,string dbName,string[] objectNames,bool alter){
			try{
				ShowFileInQueryAnalyzer(server,dbName,GetObjectFiles(server,dbName,objectNames,alter));
			}catch(Exception exc){ MessageBox.Show(ClientException.GetMessages(exc)); }
		}
		private static void ShowFileInQueryAnalyzer(string fileName){
			ShowFileInQueryAnalyzer("","",fileName);
		}
		private static void ShowFileInQueryAnalyzer(string server,string dbName,string fileName){
			ShowFileInQueryAnalyzer(server,dbName,new string[]{fileName},false);
		}
		private static void ShowFileInQueryAnalyzer(string server,string dbName,string[] fileNames){
			ShowFileInQueryAnalyzer(server,dbName,fileNames,false);
		}
		private static void ShowFileInQueryAnalyzer(string server,string dbName,string[] fileNames,bool alter){
			StringList sl = new StringList();
			foreach( string fileName in fileNames )
				if( fileName != "" )sl.Add(fileName);
			fileNames = sl;
			if( alter )SQLDMONET.CreateToAlter(fileNames);
			try{Show_SqlWb(server,dbName,fileNames);
			}catch{
				try{
					Show_ISqlW(server,dbName,fileNames[0]);
				}catch(Exception exc){
					MessageBox.Show(ClientException.GetMessages(exc));
				}
			}
		}
		private static void Show_ISqlW(string server,string dbName,string fileName){
			Process.Start(@"C:\Program Files\Microsoft SQL Server\80\Tools\Binn\isqlw.exe",
										 "-S "+server+" -d "+dbName+" -E -f \""+fileName+"\"");
		}
		private static void Show_SqlWb(string server,string dbName,string fileName){
			Show_SqlWb(server,dbName,new string[]{fileName});
		}
		private static void Show_SqlWb(string server,string dbName,string[] fileNames){
			string fileList = "\""+string.Join("\",\"",fileNames)+"\"";
			string S = server != "" ? "-E -S "+server : "";
			string d = dbName != "" ? " -d "+dbName : "";
			Process.Start(StudioName+".exe",S+" "+d+" "+fileList+" -nosplash");
		}
		private void GetDepends(string server,string dbName,string objectName){
			try{
				string schema = GetObjectSchema(objectName);
				objectName = GetObjectName(objectName);
				FormMain dbObjectsForm =  new FormMain(server,"",dbName,"",objectName,SQLDMONET.Depends(server,dbName,objectName,schema));
				dbObjectsForm.Show();
			}catch(Exception exc){ MessageBox.Show(ClientException.GetMessages(exc)); }
		}
		private void RemoveRows(){
			ArrayList al = new ArrayList();
			for( int i = 0; i < dvDBObjects.Count; i++ )
				if( dgDBObjects.IsSelected(i) )al.Add(dvDBObjects[i].Row);
			foreach( DataRow rv in al )
				rv.Delete();
			dsDBObjects.AcceptChanges();
		}
		private static string GetTemplate(string template){return Regex.Match(template,"^%?(.+?)%?$").Groups[1].Value;}
		private void SetDBTemplate(){
			DBTemplate = GetTemplate(DBTemplate);
			if( chkPercsent.Checked )DBTemplate = "%"+DBTemplate+"%";
			Application.DoEvents();
		}
		private string GetObjectName(string text){return Regex.Replace(text,"[^.]+\\.\\[(.+?)\\]","$1");}
		private string GetObjectSchema(string text){return Regex.Match(text,"^(.+?)\\.").Groups[1].Value;}
		#endregion



	}

	#region SQLDMONET
	public class SQLDMONET:IDisposable{
		#region DB_SQL_CREATE_SP_FIND
		private const string DB_SQL_CREATE_SP_FIND = @"
SET NOCOUNT ON

SET @Text = REPLACE(@Text,'_','[_]')

CREATE TABLE #Text (ID int IDENTITY,Text varchar(7000))

DECLARE @Find TABLE(Name sysname,Type char(2),Line varchar(7777))
DECLARE  cur CURSOR READ_ONLY
FOR select name,xtype from sysobjects where not xtype IN('F','U','D','S','PK','UQ')

DECLARE @name sysname,@xtype char(2),@Line varchar(8000),@ID int
OPEN cur

FETCH NEXT FROM cur INTO @name,@xtype
WHILE @@fetch_status = 0 BEGIN
	INSERT INTO #Text	exec sp_helptext @name
	SELECT @Line = '',@ID = 0
	WHILE 1 = 1 BEGIN
		SELECT @Line =  @Line + Text,@ID = ID FROM #Text WHERE Text LIKE '%'+@Text+'%' AND ID > @ID
		IF @@ROWCOUNT = 0	BREAK
	END
	IF @Line > '' INSERT INTO @Find VALUES(@name,@xtype,@Line)
	TRUNCATE TABLE #Text
	FETCH NEXT FROM cur INTO @name,@xtype
END -- Dimok 2

CLOSE cur
DEALLOCATE cur

SELECT Name AS NameFrom,Type,Line AS TextFrom FROM @Find ORDER BY Name
";
		#endregion

		#region Members
		public const DMO.SQLDMO_SCRIPT_TYPE DB_SCRIPT_TYPE_ALL =
			DMO.SQLDMO_SCRIPT_TYPE.SQLDMOScript_PrimaryObject |
			DMO.SQLDMO_SCRIPT_TYPE.SQLDMOScript_DRI_All |
			DMO.SQLDMO_SCRIPT_TYPE.SQLDMOScript_Indexes;
		public const DMO.SQLDMO_SCRIPT_TYPE DB_SCRIPT_TYPE_ALL_CREATE = DB_SCRIPT_TYPE_ALL |
			DMO.SQLDMO_SCRIPT_TYPE.SQLDMOScript_Drops |
			DMO.SQLDMO_SCRIPT_TYPE.SQLDMOScript_Triggers;
		private const string connectionRaw = "Persist Security Info=False;Initial Catalog=~DBName~;Data Source=~DBServer~;Trusted_Connection=Yes;Application Name=;Workstation ID=Admin.Dimok";

		private static object m = System.Reflection.Missing.Value;
		private DMO.SQLServerClass sqlServer = new DMO.SQLServerClass();
		private string serverName;
		public static string GetConnString(string dbServer,string dbName){ return connectionRaw.Replace("~DBServer~",dbServer).Replace("~DBName~",dbName); }
		public string GetConnString(string dbName){ return GetConnString(serverName,dbName); }

		public SQLDMONET(string serverName){
			this.serverName = serverName;
		}

		public string[] Databases{
			get{
				StringList slDBs = new StringList();
				if( serverName != "" )
					try{
						foreach( DMO.Database db in SqlServer.Databases )
							slDBs.Add(db.Name);
					}catch(Exception exc){MessageBox.Show(ClientException.GetExceptions(exc));}
				return slDBs;
			}
		}
		public DMO.Database Database(string dbName){return (DMO.Database)SqlServer.Databases.Item(dbName,m);}
		public DMO.Database2 Database2(string dbName){return (DMO.Database2)SqlServer.Databases.Item(dbName,m);}
		public DMO.DBObject Object(string dbName,string objectName,string schema){
			try{
				return Database(dbName).GetObjectByName(objectName,DMO.SQLDMO_OBJECT_TYPE.SQLDMOObj_AllDatabaseObjects,schema);
			}catch(Exception exc){
				if( exc.Message.ToLower().IndexOf("not found") > 0 ) return null;
				throw;
			}
		}
		#endregion

		#region ObjectText
		private static string NL{get{return Environment.NewLine;}}
		private const string SQL_QUOTED_IDENTIFIER = @"SET QUOTED_IDENTIFIER (ON|OFF)\s+GO\s+SET ANSI_NULLS (ON|OFF)\s+GO\s+";
		private static string SQL_BEGIN_TRAN{get{return "BEGIN TRAN"+NL+"GO"+NL;}}
		private const string SQL_COMMIT_TRAN = "IF @@ERROR = 0 COMMIT TRAN";

		public static string ObjectText(string serverName,string dbName,string objectName,bool alter){
			return ObjectText("",serverName,dbName,objectName,m,alter);
		}
		public static string ObjectText(string path,string serverName,string dbName,string objectName,object fileName,bool alter){
			using(SQLDMONET dmo = new SQLDMONET(serverName))
				return dmo.ObjectText(path,dbName,objectName,fileName,alter);
		}
		public string ObjectText(string path,string dbName,string objectName,object fileName,bool alter){
			try{
				return ObjectText(path,dbName,objectName,DB_SCRIPT_TYPE_ALL,fileName,alter);
			}catch(ThreadAbortException){return "";}
		}
		/// <summary>
		/// Get object's text
		/// </summary>
		/// <param name="path"></param>
		/// <param name="dbName"></param>
		/// <param name="objectName"></param>
		/// <param name="scriptType"></param>
		/// <param name="fileName">File Name</param>
		/// <param name="alter"></param>
		/// <returns>File Name or object's text if fileName == System.Reflection.Missing.Value</returns>
		public string ObjectText(string path,string dbName,string objectName,DMO.SQLDMO_SCRIPT_TYPE scriptType,object fileName,bool alter){
			if( objectName == "" || Regex.IsMatch(objectName,".+[.]\\[\\]") )return "";
			if( fileName.ToString() == "" )fileName = BuildSqlFileName(path,serverName,dbName,objectName);
			Match mObject = Regex.Match(objectName,"(?<owner>.+)[.]\\[(?<name>.+)\\]");
			string owner = mObject.Groups["owner"].Value;
			objectName = mObject.Groups["name"].Value;
			try{
				DMO.Database2 db = Database2(dbName);
				DMO.DBObject dbObject = db.GetObjectByName(objectName,DMO.SQLDMO_OBJECT_TYPE.SQLDMOObj_AllDatabaseObjects,owner);
				string text = dbObject.Type != DMO.SQLDMO_OBJECT_TYPE.SQLDMOObj_UserDefinedFunction ?
					dbObject.Script(scriptType,m,DMO.SQLDMO_SCRIPT2_TYPE.SQLDMOScript2_Default) :
					db.UserDefinedFunctions.Item(objectName,owner).Script(scriptType,m,DMO.SQLDMO_SCRIPT2_TYPE.SQLDMOScript2_Default);
				if( alter )text = CreateToAlter(text);
				text = Regex.Replace(text,SQL_QUOTED_IDENTIFIER,"").Trim("\r\n \t".ToCharArray());
				if( fileName == m )return text;
				return SaveSqlToFile(text,fileName+"");
			}catch(System.Threading.ThreadAbortException){
				return "";
			}catch(System.Runtime.InteropServices.COMException exc){
				if( exc.Message.ToLower().IndexOf("not found") > 0 ) return "";
				throw;
			}catch(Exception exc){
				MessageBox.Show(exc.Message+Environment.NewLine+exc.StackTrace);
				return "";
			}
		}
		public static string BuildSqlFileName(string path,string server,string dbName,string objectName){
			Match mObject = Regex.Match(objectName,"(?<owner>.+)[.]\\[(?<name>.+)\\]");
			string owner = mObject.Groups["owner"].Value;
			objectName = mObject.Groups["name"].Value;
			string fileName = Path.Combine(path.ToUpper(),server.ToUpper()+"\\"+dbName.ToUpper())+"\\"+objectName+"("+owner+")"+".sql";

			//string fileName = Path.Combine(path.ToUpper(),server.ToUpper()+"\\"+dbName.ToUpper())+"\\"+objectName+".sql";
			Directory.CreateDirectory(Path.GetDirectoryName(fileName+""));
			return fileName;
		}
		public static string SaveSqlToFile(string sql,string path,string serverName,string dbName,string objectName){
			return SaveSqlToFile(sql,BuildSqlFileName(path,serverName,dbName,objectName));
		}
		public static string SaveSqlToFile(string sql,string fileName){
			if( File.Exists(fileName) && IsSqlEqual(sql,FileManager.GetTextFromFile(fileName)) )return fileName;
			FileManager.ShiftVersions(fileName,"(00)");
			string fileLast = FileManager.GetSureFileName(fileName,"00");
			if( fileName.ToLower() != fileLast.ToLower() )File.Move(fileName,fileLast);
			return FileManager.GetFileFromBytes(sql,fileName,false);
		}
		private static bool IsSqlEqual(string sql1,string sql2){
			return sql1 == sql2 || sql1 == CreateToAlter(sql2) || sql2 == CreateToAlter(sql1);
		}
		private static string GetFileName(string fileName,string text){
			string fileLast = FileManager.GetLastVersion(fileName,"(00)");
			if( !File.Exists(fileLast) )return fileName;
			string textLast = FileManager.GetTextFromFile(fileLast);
			return text ==  textLast || text == CreateToAlter(textLast) ?
				fileLast : FileManager.GetSureFileName(fileName,"00");
		}
		#endregion

		#region Depends
		public static DBObjectsDS Depends(string dbServer,string dbName,string objectName,string schema){
			using(SQLDMONET dmo = new SQLDMONET(dbServer)){
				return dmo.Depends(dbName,objectName,schema);
			}
		}
		public DBObjectsDS Depends(string dbName,string objectName,string schema){
			DBObjectsDS dsDbO = new DBObjectsDS();
			if( objectName != "" ){
				DBObjectsDS.ObjectsDataTable dtDepends = dsDbO.Objects;
				dtDepends.PrimaryKey = new DataColumn[]{dtDepends.Columns["NameFrom"]};
				DMO.QueryResults que = Object(dbName,objectName,schema).EnumDependencies(DMO.SQLDMO_DEPENDENCY_TYPE.SQLDMODep_Children | DMO.SQLDMO_DEPENDENCY_TYPE.SQLDMODep_FirstLevelOnly);
				for( int i = 1; i <= que.Rows; i++ )
					dtDepends.AddObjectsRow(que.GetColumnString(i,2),"","",false,"","",0,0,"",true);
				DBObjectsDS.ObjectsDataTable dtObjects = FindDepends(dbName,"%"+objectName+"%",schema);
				dsDbO.Merge(dtObjects);
			}
			return dsDbO;
		}
		private DBObjectsDS.ObjectsDataTable FindDepends(string dbName,string pattern,string schema){
			using(SqlConnection conn = new SqlConnection(GetConnString(dbName))){
				DBObjectsDS.ObjectsDataTable dtObjects = new DBObjectsDS().Objects;
				//SQLHelperEx.ExecuteNonQuery(conn,CommandType.Text,DB_SQL_CREATE_SP_FIND);
				//Thread.Sleep(300);
				//SQLHelperEx.ExecuteDatasetEx(conn,dtObjects,CommandType.Text,DB_SQL_CREATE_SP_FIND,new SqlParameter("@Text",pattern));
				SQLHelperEx.ExecuteDatasetEx(conn,dtObjects,SqlConstants.DB_SQL_GET_OBJECTS,pattern,schema,"%");
				if( dtObjects.Columns.Contains("D") )dtObjects.Columns.Remove("D");
				return dtObjects;
			}
		}
		#endregion

		#region Utils
		/// <returns>File Name</returns>
		public static string MakeSP___Compliant(string fileName){
			string text = FileManager.GetTextFromFile(fileName);
			text = Regex.Replace(text,"RETURN ","INSERT INTO #Return SELECT ",RegexOptions.IgnoreCase);
			return FileManager.GetFileFromBytes(text,FileManager.GetSureFileName(fileName,"{00}"),true);
		}
		public static string[] CreateToAlter(string[] files){
			StringList sl = new StringList();
			foreach( string file in files )
				sl.Add( CreateToAlter(file));
			return sl;
		}
		public static string CreateToAlter(string file){
			if( File.Exists(file) )
				return FileManager.GetFileFromBytes(CreateToAlter(FileManager.GetTextFromFile(file)),file,false);
			else{
				Regex re = new Regex("^CREATE\\s",RegexOptions.Multiline);
				return re.Replace(file,"ALTER ",1);
			}
		}
		#endregion

		public void Dispose() {
			if( IsConnected )
				sqlServer.Close();
		}

		public DMO.SQLServerClass SqlServer{
			get{Login();
				return sqlServer;
			}
		}
		private void Login(){
			if( IsConnected || serverName == "" )return;
			sqlServer.LoginSecure = true;
			sqlServer.Connect(serverName,"","");
		}
		private bool IsConnected{get{return sqlServer.VerifyConnection(DMO.SQLDMO_VERIFYCONN_TYPE.SQLDMOConn_CurrentState);}}
	}
	#endregion

	class SqlConstants{
		public const string DB_SQL_GET_OBJECTS = @"
SELECT DISTINCT NameFrom,Type,[schema],MSS,/*ISNULL(object_definition(id),'')*/ '' AS TextFrom FROM(

SELECT so.object_id,so.name NameFrom ,so.type Type,s.name [Schema],Is_MS_Shipped MSS
FROM sys.all_objects so INNER JOIN  sys.schemas s ON so.schema_id = s.schema_id
WHERE so.object_id > 0
	AND RTRIM(so.type) NOT IN('IT','S','SQ')
	AND so.name LIKE @Name
	AND s.name LIKE @Schema
	AND so.type LIKE @Type

UNION ALL

SELECT so.object_id,so.name NameFrom ,so.type Type,s.name [Schema],Is_MS_Shipped MSS
FROM syscomments sc INNER JOIN sys.all_objects so ON sc.id = so.object_id
INNER JOIN  sys.schemas s ON so.schema_id = s.schema_id
WHERE	so.object_id > 0 -- AND so.status >= 0
	AND RTRIM(so.type) IN ('C','D','FN','IF','P','TF','TR','V')
	AND	(sc.text LIKE N'' + @Name + '')
	AND s.name LIKE @Schema
	AND so.type LIKE @Type

UNION ALL

SELECT 0,t.name,'DT',s.name,0 FROM sys.types t
INNER JOIN  sys.schemas s ON t.schema_id = s.schema_id
WHERE t.user_type_id > 256
			AND t.name LIKE @Name
			AND s.name LIKE @Schema
			AND 'DT' LIKE @Type


UNION ALL

SELECT so.object_id,so.name NameFrom ,so.type Type,s.name [Schema],Is_MS_Shipped MSS
FROM syscolumns sc INNER JOIN sys.all_objects so ON sc.id = so.object_id
INNER JOIN  sys.schemas s ON so.schema_id = s.schema_id
WHERE so.object_id > 0 --AND so.status >= 0
	AND sc.name LIKE @Name
	AND s.name LIKE @Schema
	AND so.type LIKE @Type

)T
WHERE [schema] <> 'sys' AND (NOT NameFrom LIKE 'dt_%' OR NOT Type IN ('P','U'))
";
	}
}
